package com.neu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neu.base.AuthContants;
import com.neu.base.Result;
import com.neu.entity.*;
import com.neu.entity.DTO.InvitationDTO;
import com.neu.entity.security.LoginUser;
import com.neu.events.UserUpdateEvent;
import com.neu.mapper.InvitationMapper;
import com.neu.service.EmailService;
import com.neu.service.InvitationService;
import com.neu.service.ProjectUserRoleService;
import com.neu.service.UserService;
import com.neu.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class InvitationServiceImpl extends ServiceImpl<InvitationMapper, Invitation> implements InvitationService {
    @Autowired
    private UserService userService;
    @Autowired
    private EmailService emailService;
    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private ProjectUserRoleService projectUserRoleService;

    @Value("${swpt.jwt.invite-expiration}")
    private Long inviteExpiration;
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Override
    public void sendProjectInviteLink(List<String> noticeUserIds, Project project, Role role, LoginUser loginUser,String noticeId) throws Exception {
        if (noticeUserIds.isEmpty()) {
            return;
        }
        List<User> users = userService.listByIds(noticeUserIds);
        // 创建邀请记录
        List<Invitation> invitations = new ArrayList<>();
        for (User user : users) {
            // 创建邀请记录
            Invitation invitation = new Invitation();
            invitation.setInvitationId(UUID.randomUUID().toString().replace("-", ""));
            invitation.setProjectId(project.getProjectId());
            invitation.setNoticeId(noticeId);
            invitation.setProjectName(project.getProjectName());
            invitation.setInviterId(loginUser.getUserId()); // 获取当前用户ID
            invitation.setInviteeId(user.getUserId());
            if (user.getEmail() != null && !user.getEmail().isEmpty()) {
                invitation.setInviteeEmail(user.getEmail());
            } else {
                // 处理无邮箱的情况，可能需要其他逻辑
                continue;
            }
            invitation.setRoleId(role.getRoleId());
            invitation.setRoleName(role.getRoleName());
            invitation.setStatus("0"); // 待处理
            String token = UUID.randomUUID().toString().replace("-", "");
            redisUtil.set(AuthContants.REDIS_KEY_INVITE_TOKEN + user.getUsername(), token, inviteExpiration); // 保存到redis中
            invitation.setToken(token);
            invitation.setExpiresAt(LocalDateTime.now().plusDays(1)); // 设置过期时间
            invitations.add(invitation);
        }
        // 批量保存邀请记录
        if (!invitations.isEmpty()) {
            this.saveBatch(invitations);
        }
        // 发送邀请邮件
        emailService.sendInviteEmails(invitations, project, role);
    }

    @Override
    public Result updateInvitationStatus(String token, String status) {
        if(!StringUtils.hasText(token)){
            return Result.error("非本人操作！");
        }
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userId = loginUser.getUserId(); // 获取当前登录用户ID
        // 验证邀请是否已经处理
        LambdaQueryWrapper<Invitation> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Invitation::getToken, token);
        Invitation invitation= this.getOne(queryWrapper1);
        if(invitation==null){
            return Result.error("邀请不存在");
        }

        if(!invitation.getInviteeId().equals(userId)){
            return Result.error("无权限处理邀请");
        }else{
            // 验证邀请并更新状态 从redis中获取token
            String username = loginUser.getUsername();
            String tokenInRedis = (String) redisUtil.get(AuthContants.REDIS_KEY_INVITE_TOKEN + username);
            if (tokenInRedis == null || !tokenInRedis.equals(token)) {
                return Result.error("邀请已失效");
            }
            if(!invitation.getStatus().equals("0")){
                return Result.error("邀请已处理");
            }
        }

        // 更新邀请状态
        invitation.setStatus(status);
        if (status.equals("1")) {
            // 添加用户到项目中
            ProjectUserRole projectUserRole = new ProjectUserRole();
            projectUserRole.setProjectId(invitation.getProjectId());
            projectUserRole.setRoleId(invitation.getRoleId());
            projectUserRole.setUserId(userId);
            projectUserRoleService.save(projectUserRole);

            // 更新登录用户的项目角色,主要是为了更新上下文和redis中的用户信息
            User user = userService.getById(userId);
            if (user.getUserId().equals(loginUser.getUserId())) {
                eventPublisher.publishEvent(new UserUpdateEvent(this, user));
            }
        }

        return Result.success(this.updateById(invitation));
    }

    @Override
    public Result getInvitationDetails(String token) {
        LambdaQueryWrapper<Invitation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Invitation::getToken, token);
        Invitation invitation = this.getOne(queryWrapper);
        if (invitation == null) {
            return Result.error("邀请不存在");
        }
        InvitationDTO invitationDTO = new InvitationDTO();
        BeanUtil.copyProperties(invitation, invitationDTO);
        User inviter = userService.getById(invitation.getInviterId());
        User invitee = userService.getById(invitation.getInviteeId());
        invitationDTO.setInviterName(inviter.getUsername());
        invitationDTO.setInviteeName(invitee.getUsername());

        return Result.success(invitationDTO);

    }
}
